package com.ysu.yybk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sun.javafx.binding.StringFormatter;
import com.ysu.yybk.entity.Log;
import com.ysu.yybk.entity.checkin.Checkin;
import com.ysu.yybk.entity.course.Course;
import com.ysu.yybk.entity.course.CourseStudent;
import com.ysu.yybk.entity.member.Teacher;
import com.ysu.yybk.form.checkin.TeacherCheckinStart;
import com.ysu.yybk.mapper.LogMapper;
import com.ysu.yybk.mapper.checkin.CheckinMapper;
import com.ysu.yybk.mapper.course.CourseMapper;
import com.ysu.yybk.mapper.member.TeacherMapper;
import com.ysu.yybk.service.CheckinTeacherService;
import com.ysu.yybk.util.TimeUtil;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author ：lhw
 * @date ：Created in 2019/11/18 23:16
 */
@Service
public class CheckinTeacherServiceImpl implements CheckinTeacherService {
    private static final Logger logger = LoggerFactory.getLogger(CheckinTeacherServiceImpl.class);
    @Autowired
    CourseMapper courseMapper;

    @Autowired
    CheckinMapper checkinMapper;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    LogMapper logMapper;

    @Autowired
    TeacherMapper teacherMapper;

    /**
     * 签到发起接口
     * error_code 1 不在签到时间 2 当前时间无课 3 有已发起签到 0成功
     * @param checkinStart
     * @return
     */
    @Override
    public Map<String, Object> start(TeacherCheckinStart checkinStart) {

        if(TimeUtil.getTime() == -1){
            Map<String,Object> result =  new HashMap<String, Object>();
            result.put("error_code",1);
            return result;
        }
        List<Course> courseList = courseMapper.selectList(
                new QueryWrapper<Course>().eq("teacher_id",checkinStart.getTeacherId())
                        .le("week_start", TimeUtil.getWeek())
                        .ge("week_end",TimeUtil.getWeek())
                        .eq("day",TimeUtil.getDate())
                        .eq("time",TimeUtil.getTime())
        );

        if(courseList.isEmpty()){
            Map<String,Object> result =  new HashMap<String, Object>();
            result.put("error_code",2);
            return result;
        }

        String courseId = courseList.get(0).getId();

        Checkin newCheckin = null;

        RReadWriteLock writeLock = redissonClient.getReadWriteLock(courseId);
        writeLock.writeLock().lock(5, TimeUnit.SECONDS);


        try{
            newCheckin = writeStart(courseId,checkinStart);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw e;
        }finally {
            writeLock.writeLock().unlock();
        }

        if(newCheckin == null){
            Map<String,Object> result =  new HashMap<String, Object>();
            result.put("error_code",3);
            return result;
        }



        Map<String,Object> result =  new HashMap<String, Object>();
        result.put("error_code",0);
        result.put("checkin_id",newCheckin.getId());
        result.put("course_id",newCheckin.getCourseId());
        result.put("locate",newCheckin.getLocate());

        writeLog(checkinStart,courseId);

        return result;
    }

    //此函数需要锁住
    @Transactional
    //@Klock(keys = {"#couseId"},lockType = LockType.Write)
    public Checkin writeStart(String courseId, TeacherCheckinStart checkinStart){
        List<Checkin> checkins = checkinMapper.selectList(
                new QueryWrapper<Checkin>().eq("course_id", courseId)
                        .isNull("end_time")
                       // .last(" for update")
        );
        //List<Checkin> checkins = checkinMapper.getListForUpdate(courseId);

        if(!checkins.isEmpty()){
            return null;
        }

        Checkin newCheckin = new Checkin();

        newCheckin.setCourseId(courseId);
        newCheckin.setTeacherId(checkinStart.getTeacherId());
        newCheckin.setLocate(checkinStart.getLocate());
        newCheckin.setPhoto(checkinStart.getPhoto());
        newCheckin.setLatitude(checkinStart.getLatitude());
        newCheckin.setLongitude(checkinStart.getLongitude());
        newCheckin.setStartTime(new Timestamp(System.currentTimeMillis()));

        checkinMapper.insert(newCheckin);

        return newCheckin;
    }

    private void writeLog(TeacherCheckinStart checkinStart,String courseId){
        try {
            Teacher teacher = teacherMapper.selectOne(new QueryWrapper<Teacher>()
                    .eq("id",checkinStart.getTeacherId()));

            Log log = new Log();
            log.setCourseId(courseId);
            log.setCreateTime(new Timestamp(System.currentTimeMillis()));
            log.setInstitute(teacher.getInstitute());
            log.setReason("checkin");
            log.setTeacherId(teacher.getId());
            log.setTeacherName(teacher.getName());

            logMapper.insert(log);

        }catch (Exception e){

        }
    }
}
